Canvas 从入门到劝朋友放弃(图解版) | 您所在的位置:网站首页 › duck canvas是什么面料 › Canvas 从入门到劝朋友放弃(图解版) |
本文简介
点赞 + 关注 + 收藏 = 学会了 在前端领域,如果只是懂 Vue 或者 React ,未来在职场的竞争力可能会比较弱。 根据我多年在家待业经验来看,前端未来在 数据可视化 和 AI 这两个领域会比较香,而 Canvas 是数据可视化在前端方面的基础技术。 本文就用光的速度将 canvas 给入门了。 要入门一个技术,前期最重要是快!所以本文只讲入门内容,能应付简单项目。深入的知识点会在其他文章讲解。 Canvas 是什么? Canvas 中文名叫 “画布”,是 HTML5 新增的一个标签。 Canvas 允许开发者通过 JS在这个标签上绘制各种图案。 Canvas 拥有多种绘制路径、矩形、圆形、字符以及图片的方法。 Canvas 在某些情况下可以 “代替” 图片。 Canvas 可用于动画、游戏、数据可视化、图片编辑器、实时视频处理等领域。 Canvas 和 SVG 的区别 CanvasSVG用JS动态生成元素(一个HTML元素)用XML描述元素(类似HTML元素那样,可用多个元素来描述一个图形)位图(受屏幕分辨率影响)矢量图(不受屏幕分辨率影响)不支持事件支持事件数据发生变化需要重绘不需要重绘 就上面的描述而言可能有点难懂,你可以打开 AntV 旗下的图形编辑引擎做对比。G6 是使用 canvas 开发的,X6 是使用 svg 开发的。 我的建议是:如果要展示的数据量比较大,比如一条数据就是一个元素节点,那使用 canvas 会比较合适;如果用户操作的交互比较多,而且对清晰度有要求(矢量图),那么使用 svg 会比较合适。 起步 学习前端一定要动手敲代码,然后看效果展示。 起步阶段会用几句代码说明 canvas 如何使用,本例会画一条直线。 画条直线 在 HTML 中创建 canvas 元素 通过 js 获取 canvas 标签 从 canvas 标签中获取到绘图工具 通过绘图工具,在 canvas 标签上绘制图形moveTo 、 lineTo 和 stroke 方法暂时可以不用管,它们的作用是绘制图形,这些方法在后面会讲到~ 注意点 1、默认宽高canvas 有 默认的 宽度(300px) 和 高度(150px) 如果不在 canvas 上设置宽高,那 canvas 元素的默认宽度是300px,默认高度是150px。 2、设置 canvas 宽高canvas 元素提供了 width 和 height 两个属性,可设置它的宽高。 需要注意的是,这两个属性只需传入数值,不需要传入单位(比如 px 等)。 3、不能通过 CSS 设置画布的宽高使用 css 设置 canvas 的宽高,会出现 内容被拉伸 的后果!!! canvas 的默认宽度是300px,默认高度是150px。 如果使用 css 修改 canvas 的宽高(比如本例变成 400px * 400px),那宽度就由 300px 拉伸到 400px,高度由 150px 拉伸到 400px。 使用 js 获取 canvas 的宽高,此时返回的是 canvas 的默认值。最后出现的效果如上图所示。 4、线条默认宽度和颜色线条的默认宽度是 1px ,默认颜色是黑色。 但由于默认情况下 canvas 会将线条的中心点和像素的底部对齐,所以会导致显示效果是 2px 和非纯黑色问题。 5、IE兼容性高暂时只有 IE 9 以上才支持 canvas 。但好消息是 IE 已经有自己的墓碑了。 如需兼容 IE 7 和 8 ,可以使用 ExplorerCanvas 。但即使是使用了 ExplorerCanvas 仍然会有所限制,比如无法使用 fillText() 方法等。 基础图形 坐标系 在绘制基础图形之前,需要先搞清除 Canvas 使用的坐标系。 Canvas 使用的是 W3C 坐标系 ,也就是遵循我们屏幕、报纸的阅读习惯,从上往下,从左往右。 W3C 坐标系 和 数学直角坐标系 的 X轴 是一样的,只是 Y轴 的反向相反。 W3C 坐标系 的 Y轴 正方向向下。 直线 一条直线最简单的起步方式是画一条直线。这里所说的 “直线” 是几何学里的 “线段” 的意思。 需要用到这3个方法: moveTo(x1, y1):起点坐标 (x, y) lineTo(x2, y2):下一个点的坐标 (x, y) stroke():将所有坐标用一条线连起来起步阶段可以先这样理解。 上面的代码所呈现的效果,可以看下图解释(手不太聪明,画得不是很标准,希望能看懂) 如需画多条直线,可以用会上面那几个方法。 仔细观察一下,为什么两条线的粗细不一样的? 明明使用的方法都是一样的,只是第二条直线的 Y轴 的值是有小数点。 答:默认情况下 canvas 会将线条的中心点和像素的底部对齐,所以会导致显示效果是 2px 和非纯黑色问题。 上图每个格子代表 1px。 线的中心点会和画布像素点的底部对齐,所以会线中间是黑色的,但由于一个像素就不能再切割了,所以会有半个像素被染色,就变成了浅灰色。 所以如果你设置的 Y轴 值是一个整数,就会出现上面那种情况。 设置样式 lineWidth:线的粗细 strokeStyle:线的颜色 lineCap:线帽:默认: butt; 圆形: round; 方形: square开辟新路径的方法: beginPath()在绘制多条线段的同时,还要设置线段样式,通常需要开辟新路径。 要不然样式之间会相互污染。 比如这样 如果不想相互污染,需要做2件事: 使用 beginPath() 方法,重新开一个路径 设置新线段的样式(必须项)如果上面2步却了其中1步都会有影响。 只使用 beginPath()第一条线的样式会影响之后的线。 但如果使用了 beginPath() ,后面的线段不会影响前面的线段。 这个情况会反过来,后面的线能影响前面的线。 在设置 beginPath() 的同时,也各自设置样式。这样就能做到相互不影响了。 和 直线 差不多,都是使用 moveTo() 、lineTo() 和 stroke() 方法可以绘制折线。 画这种折线,最好在草稿纸上画一个坐标系,自己计算并描绘一下每个点大概在什么什么位置,最后在 canvas 中看看效果。 矩形根据前面的基础,我们可以 使用线段来描绘矩形,但 canvas 也提供了 rect() 等方法可以直接生成矩形。 使用线段描绘矩形可以使用前面画线段的方法来绘制矩形 上面的代码几个点分别对应下图。 上面的代码可以这样理解 fillRect() 和 strokeRect() 方法差不多,但 fillRect() 的作用是填充。 需要注意的是,fillStyle 必须写在 fillRect() 之前,不然样式不生效。 同时使用 strokeRect() 和 fillRect() 会产生描边和填充的效果 rect() 和 fillRect() 、strokeRect() 的用法差不多,唯一的区别是: strokeRect() 和 fillRect() 这两个方法调用后会立即绘制;rect() 方法被调用后,不会立刻绘制矩形,而是需要调用 stroke() 或 fill() 辅助渲染。 等价公式: cxt.strokeStyle = 'red', cxt.rect(50, 50, 200, 100) cxt.stroke() // 等价于 cxt.strokeStyle = 'red' cxt.strokerect(50, 50, 200, 100) // ----------------------------- cxt.fillStyle = 'hotpink' cxt.rect(50, 50, 200, 100) cxt.fill() // 等价于 cxt.fillStyle = 'yellowgreen' cxt.fillRect(50, 50, 200, 100) 使用 clearRect() 清空矩形使用 clearRect() 方法可以清空指定区域。 clearRect(x, y, width, height)其语法和创建 cxt.rect() 差不多。 canvas 画布元素是矩形,所以可以通过下面的代码把整个画布清空掉。 // 省略部分代码 cxt.clearRect(0, 0, cnv.width, cnv.height)要清空的区域:从画布左上角开始,直到画布的宽和画布的高为止。 多边形Canvas 要画多边形,需要使用 moveTo() 、 lineTo() 和 closePath() 。 三角形虽然三角形是常见图形,但 canvas 并没有提供类似 rect() 的方法来绘制三角形。 需要确定三角形3个点的坐标位置,然后使用 stroke() 或者 fill() 方法生成三角形。 注意,默认情况下不会自动从最后一个点连接到起点。最后一步需要设置一下 cxt.lineTo(50, 50) ,让它与 cxt.moveTo(50, 50) 一样。这样可以让路径回到起点,形成一个闭合效果。 但这样做其实是有点问题的,而且也比较麻烦,要记住起始点坐标。 上面的闭合操作,如果遇到设置了 lineWidth 或者 lineJoin 就会有问题,比如: 当线段变粗后,起始点和结束点的链接处,拐角就出现“不正常”现象。 如果需要真正闭合,可以使用 closePath() 方法。 使用 cxt.closePath() 可以自动将终点和起始点连接起来,此时看上去就正常多了。 菱形有一组邻边相等的平行四边形是菱形 要绘制直线类型的图形,在草稿纸上标记出起始点和每个拐角的点,然后再连线即可。相对曲线图形来说,直线图形是比较容易的。 圆形绘制圆形的方法是 arc()。 语法: arc(x, y, r, sAngle, eAngle,counterclockwise) x 和 y: 圆心坐标 r: 半径 sAngle: 开始角度 eAngle: 结束角度 counterclockwise: 绘制方向(true: 逆时针; false: 顺时针),默认 false开始角度和结束角度,都是以弧度为单位。例如 180°就写成 Math.PI ,360°写成 Math.PI * 2 ,以此类推。 在实际开发中,为了让自己或者别的开发者更容易看懂弧度的数值,1°应该写成 Math.PI / 180。 100°: 100 * Math.PI / 180 110°: 110 * Math.PI / 180 241°: 241 * Math.PI / 180注意:绘制圆形之前,必须先调用 beginPath() 方法!!! 在绘制完成之后,还需要调用 closePath() 方法!!! 如果使用 arc() 方法画圆时,没做到刚好绕完一周(360°)就直接闭合路径,就会出现半圆的状态。 上面的代码中,cxt.arc 最后一个参数没传,默认是 false ,所以是顺时针绘制。 如果希望半圆的弧面在上方,可以将 cxt.arc 最后一个参数设置成 true 使用 arc() 方法画半圆时,如果最后不调用 closePath() 方法,就不会出现闭合路径。也就是说,那是一条弧线。 在 canvas 中,画弧线有2中方法:arc() 和 arcTo() 。 arc() 画弧线如果想画一条 0° ~ 30° 的弧线,可以这样写 原理如下图所示,红线代表画出来的那条弧线。 arcTo() 的使用方法会更加复杂,如果初学看不太懂的话可以先跳过,看完后面的再回来补补。 语法: arcTo(cx, cy, x2, y2, radius) cx: 两切线交点的横坐标 cy: 两切线交点的纵坐标 x2: 结束点的横坐标 y2: 结束点的纵坐标 radius: 半径其中,(cx, cy) 也叫控制点,(x2, y2) 也叫结束点。 是不是有点奇怪,为什么没有 x1 和 y1 ? (x1, y1) 是开始点,通常是由 moveTo() 或者 lineTo() 提供。 arcTo() 方法利用 开始点、控制点和结束点形成的夹角,绘制一段与夹角的两边相切并且半径为 radius 的圆弧。 举个例子 基础样式 前面学完基础图形,接下来可以开始了解一下如何设置元素的基础样式。 描边 stroke()前面的案例中,其实已经知道使用 stroke() 方法进行描边了。这里就不再多讲这个方法。 线条宽度 lineWidthlineWidth 默认值是 1 ,默认单位是 px。 语法: lineWidth = 线宽使用 strokeStyle 可以设置线条颜色 语法: strokeStyle = 颜色值为了展示方便,我将 lineWidth 设为 20。 线帽 lineCap线帽指的是线段的开始和结尾处的样式,使用 lineCap 可以设置 语法: lineCap = '属性值'属性值包括: butt: 默认值,无线帽 square: 方形线帽 round: 圆形线帽使用 square 和 round 的话,会使线条变得稍微长一点点,这是给线条增加线帽的部分,这个长度在日常开发中需要注意。 线帽只对线条的开始和结尾处产生作用,对拐角不会产生任何作用。 拐角样式 lineJoin如果需要设置拐角样式,可以使用 lineJoin 。 语法: lineJoin = '属性值'属性值包括: miter: 默认值,尖角 round: 圆角 bevel: 斜角使用 setLineDash() 方法可以将描边设置成虚线。 语法: setLineDash([])需要传入一个数组,且元素是数值型。 虚线分3种情况 只传1个值 有2个值 有3个以上的值此外,还可以始终 cxt.getLineDash() 获取虚线不重复的距离; 用 cxt.lineDashOffset 设置虚线的偏移位。 填充使用 fill() 可以填充图形,根据前面的例子应该掌握了如何使用 fill() 可以使用 fillStyle 设置填充颜色,默认是黑色。 非零环绕填充在使用 fill() 方法填充时,需要注意一个规则:非零环绕填充。 在使用 moveTo 和 lineTo 描述图形时,如果是按顺时针绘制,计数器会加1;如果是逆时针,计数器会减1。 当图形所处的位置,计数器的结果为0时,它就不会被填充。 这样说有点复杂,先看看例子 请看看上面的代码,我画了2个矩形,它们都没有用 beginPath() 方法开辟新路径。 内层矩形是逆时针绘制的,所以内层的值是 -1 ,它又经过外层矩形,而外层矩形是顺时针绘制,所以经过外层时值 +1,最终内层的值为 0 ,所以不会被填充。 文本 Canvas 提供了一些操作文本的方法。 为了方便演示,我们先了解一下在 Canvas 中如何给本文设置样式。 样式 font和 CSS 设置 font 差不多,Canvas 也可以通过 font 设置样式。 语法: cxt.font = 'font-style font-variant font-weight font-size/line-height font-family'如果需要设置字号 font-size,需要同事设置 font-family。 cxt.font = '30px 宋体' 描边 strokeText()使用 strokeText() 方法进行文本描边 语法: strokeText(text, x, y, maxWidth) text: 字符串,要绘制的内容 x: 横坐标,文本左边要对齐的坐标(默认左对齐) y: 纵坐标,文本底边要对齐的坐标 maxWidth: 可选参数,表示文本渲染的最大宽度(px),如果文本超出 maxWidth 设置的值,文本会被压缩。使用 strokeStyle 设置描边颜色。 使用 fillText() 可填充文本。 语法和 strokeText() 一样。 fillText(text, x, y, maxWidth)使用 fillStyle 可以设置文本填充颜色。 measureText().width 方法可以获取文本的长度,单位是 px 。 const cnv = document.getElementById('c') const cxt = cnv.getContext('2d') let text = '雷猴' cxt.font = 'bold 40px Arial' cxt.fillText(text, 40, 80) console.log(cxasureText(text).width) // 80 水平对齐方式 textAlign使用 textAlign 属性可以设置文字的水平对齐方式,一共有5个值可选 start: 默认。在指定位置的横坐标开始。 end: 在指定坐标的横坐标结束。 left: 左对齐。 right: 右对齐。 center: 居中对齐。红线是辅助参考线。 const cnv = document.getElementById('c') const cxt = cnv.getContext('2d') // 竖向的辅助线(参考线,在画布中间) cxt.moveTo(200, 0) cxt.lineTo(200, 400) cxt.strokeStyle = 'red' cxt.stroke() cxt.font = '30px Arial' // 横坐标开始位对齐 cxt.textAlign = 'start' // 默认值, cxt.fillText('雷猴 start', 200, 40) // 横坐标结束位对齐 cxt.textAlign = 'end' // 结束对齐 cxt.fillText('雷猴 end', 200, 100) // 左对齐 cxt.textAlign = 'left' // 左对齐 cxt.fillText('雷猴 left', 200, 160) // 右对齐 cxt.textAlign = 'right' // 右对齐 cxt.fillText('雷猴 right', 200, 220) // 居中对齐 cxt.textAlign = 'center' // 右对齐 cxt.fillText('雷猴 center', 200, 280)从上面的例子看,start 和 left 的效果好像是一样的,end 和 right 也好像是一样的。 在大多数情况下,它们的确一样。但在某些国家或者某些场合,阅读文字的习惯是 从右往左 时,start 就和 right 一样了,end 和 left 也一样。这是需要注意的地方。 垂直对齐方式 textBaseline使用 textBaseline 属性可以设置文字的垂直对齐方式。 在使用 textBaseline 前,需要自行了解 css 的文本基线。 用一张网图解释一下基线 textBaseline 可选属性: alphabetic: 默认。文本基线是普通的字母基线。 top: 文本基线是 em 方框的顶端。 bottom: 文本基线是 em 方框的底端。 middle: 文本基线是 em 方框的正中。 hanging: 文本基线是悬挂基线。红线是辅助参考线。 const cnv = document.getElementById('c') const cxt = cnv.getContext('2d') // 横向的辅助线(参考线,在画布中间) cxt.moveTo(0, 150) cxt.lineTo(800, 150) cxt.strokeStyle = 'red' cxt.stroke() cxt.font = '20px Arial' // 默认 alphabetic cxt.textBaseline = 'alphabetic' cxt.fillText('雷猴 alphabetic', 10, 150) // 默认 top cxt.textBaseline = 'top' cxt.fillText('雷猴 top', 200, 150) // 默认 bottom cxt.textBaseline = 'bottom' cxt.fillText('雷猴 bottom', 320, 150) // 默认 middle cxt.textBaseline = 'middle' cxt.fillText('雷猴 middle', 480, 150) // 默认 hanging cxt.textBaseline = 'hanging' cxt.fillText('雷猴 hanging', 640, 150)注意:在绘制文字的时候,默认是以文字的左下角作为参考点进行绘制 图片 在 Canvas 中可以使用 drawImage() 方法绘制图片。 渲染图片渲染图片的方式有2中,一种是在JS里加载图片再渲染,另一种是把DOM里的图片拿到 canvas 里渲染。 渲染的语法: drawImage(image, dx, dy) image: 要渲染的图片对象。 dx: 图片左上角的横坐标位置。 dy: 图片左上角的纵坐标位置。 JS版在 JS 里加载图片并渲染,有以下几个步骤: 创建 Image 对象 引入图片 等待图片加载完成 使用 drawImage() 方法渲染图片因为图片是从 DOM 里获取到的,所以一般来说,只要在 window.onload 这个生命周期内使用 drawImage 都可以正常渲染图片。 本例使用了 css 的方式,把图片的 display 设置成 none 。因为我不想被 实际开发过程中按照实际情况设置即可。 设置图片宽高前面的例子都是直接加载图片,图片默认的宽高是多少就加载多少。 如果需要指定图片宽高,可以在前面的基础上再添加两个参数: drawImage(image, dx, dy, dw, dh)image、 dx、 dy 的用法和前面一样。 dw 用来定义图片的宽度,dh 定义图片的高度。 我把图片的尺寸设为 100px * 100px,图片看上去比之前就小了很多。 截取图片截图图片同样使用drawImage() 方法,只不过传入的参数数量比之前都多,而且顺序也有点不一样了。 drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh)以上参数缺一不可 image: 图片对象 sx: 开始截取的横坐标 sy: 开始截取的纵坐标 sw: 截取的宽度 sh: 截取的高度 dx: 图片左上角的横坐标位置 dy: 图片左上角的纵坐标位置 dw: 图片宽度 dh: 图片高度总结 本文主要讲解了在 Canvas 中绘制一些基础图形,还有一些基础样式设置。 还有更多高级的玩法会在之后的文章中讲到,比如渐变、投影、滤镜等等。 代码仓库 ⭐雷猴 Canvas 推荐阅读 👍《Fabric.js 从入门到膨胀》 👍《『Three.js』起飞!》 👍《console.log也能插图!!!》 👍《纯css实现117个Loading效果》 👍《视差特效的原理和实现方法》 👍《这18个网站能让你的页面背景炫酷起来》 点赞 + 关注 + 收藏 = 学会了 |
今日新闻 |
推荐新闻 |
专题文章 |
CopyRight 2018-2019 实验室设备网 版权所有 |